#include "TaskDispatcher.h"
#include "Singleton.h"
#include "AutoLock.h"
#include "ThreadPool.h"
#include "signal.h"
#include <iostream>
#include <cstring>
#include <cerrno>

using namespace yazi::thread;
using namespace yazi::utility;

TaskDispatcher::TaskDispatcher(){
    m_tasks.clear();
}

TaskDispatcher::~TaskDispatcher(){

}

void TaskDispatcher::init(int size){
    Singleton<ThreadPool>::instance()->create(size);
    start();
}

void TaskDispatcher::assign(Task* task){
    std::cout << "TaskDispatcher assign task" << std::endl;
    AutoLock lock(&m_mutex);
    m_tasks.push_back(task);
    m_cond.signal();
}

void TaskDispatcher::handle(Task* task){
    std::cout << "TaskDispatcher handler task" << std::endl;
    ThreadPool* threadpool = Singleton<ThreadPool>::instance();
    if(threadpool->get_idle_thread_num() > 0)
        threadpool->assign(task);
    else{
        m_mutex.lock();
        m_tasks.push_front(task);
        m_mutex.unlock();
        std::cerr << "all threads are busy" << std::endl;
    }
}

void TaskDispatcher::run(){
    sigset_t mask;
    if(0 != sigfillset(&mask)){
        perror("sigfillset()");
        return;
    }
    if(0 != pthread_sigmask(SIG_SETMASK, &mask, NULL)){
        std::cerr << "pthread_sigmask() error" << std::endl;
        return;
    }
    while(true){
        m_mutex.lock();
        while(m_tasks.empty())
            m_cond.wait(&m_mutex);
        Task* task = m_tasks.front();
        m_tasks.pop_front();
        m_mutex.unlock();
        handle(task);
    }
}

